﻿using TaskManagerLib.MinimumWork;
using TaskManagerLib.Symbol;

namespace TaskManagerLib.Test;

public class DownloadTask : MiniWork
{
    public override bool IsFinished()
    {
        return Status == WorkStatus.Finish;
    }

    public string Url
    {
        get;
        set;
    }

    public string FilePath
    {
        get;
        set;
    }

    public DownloadTask(string url, string filepath)
    {
        Url = url;
        FilePath = filepath;
    }


    public override bool Resume(CancellationTokenSource cancellationTokenSource)
    {
        if (InnerTask?.Status == TaskStatus.Running)
        {
            return false;
        }

        CancellationTokenSource = cancellationTokenSource;
        Build();
        Status = WorkStatus.Ready;
        return true;
    }


    public override async Task Action()
    {
        try
        {
            using var client = new HttpClient();
            using var response = await client.GetAsync(Url, HttpCompletionOption.ResponseHeadersRead);
            response.EnsureSuccessStatusCode();

            await using var stream = await response.Content.ReadAsStreamAsync();
            var directory = Path.GetDirectoryName(FilePath);
            // 创建目录（如果不存在）
            if (!Directory.Exists(directory))
            {
                Directory.CreateDirectory(directory);
            }

            await using var fs = new FileStream(FilePath, FileMode.Create);
            var buffer = new byte[1024];
            int bytesRead;
            long totalBytesRead = 0;
            var totalBytes = response.Content.Headers.ContentLength;
            var lastNotificationTime = DateTime.MinValue;
            var notificationInterval = TimeSpan.FromMilliseconds(100);
            while ((bytesRead = await stream.ReadAsync(buffer, CancellationTokenSource?.Token ?? CancellationToken.None)) > 0)
            {
                if (CancellationTokenSource?.Token.IsCancellationRequested == true)
                {
                    Status = WorkStatus.Paused;
                    await fs.FlushAsync();
                    fs.Close();
                    return;
                }

                await fs.WriteAsync(buffer.AsMemory(0, bytesRead));
                totalBytesRead += bytesRead;

                if (!totalBytes.HasValue) continue;
                Progress = (double)totalBytesRead / totalBytes.Value;
                if (DateTime.Now - lastNotificationTime < notificationInterval) continue;
                Notification?.Invoke(new ProgressNotification()
                {
                    Progress = Progress
                });

                lastNotificationTime = DateTime.Now;
            }
            Notification?.Invoke(new ProgressNotification()
            {
                Progress = Progress
            });

            await fs.FlushAsync();
            fs.Close();
            Result = FilePath;
            Status = WorkStatus.Finish;
        }
        catch (Exception e)
        {
            Status = WorkStatus.Except;
            Console.WriteLine(e);
        }

    }


}